package com.seecen.HJM.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.seecen.HJM.constant.JwtClaimsConstant;
import com.seecen.HJM.constant.MessageConstant;
import com.seecen.HJM.enumeration.LikeStatusEnum;
import com.seecen.HJM.enumeration.RoleEnum;
import com.seecen.HJM.mapper.PlaylistBindingMapper;
import com.seecen.HJM.mapper.UserFavoriteMapper;
import com.seecen.HJM.model.dto.*;
import com.seecen.HJM.model.entity.Playlist;
import com.seecen.HJM.model.entity.Song;
import com.seecen.HJM.model.entity.UserFavorite;
import com.seecen.HJM.model.vo.PlayListVo;
import com.seecen.HJM.model.vo.PlaylistDetailVO;
import com.seecen.HJM.model.vo.SongVo;
import com.seecen.HJM.result.DataVo;
import com.seecen.HJM.result.PageResult;
import com.seecen.HJM.service.MinioService;
import com.seecen.HJM.service.PlaylistBindingService;
import com.seecen.HJM.service.PlaylistService;
import com.seecen.HJM.mapper.PlaylistMapper;
import com.seecen.HJM.util.JwtUtil;
import com.seecen.HJM.util.TypeConversionUtil;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
* @author jiachen
* @description 针对表【tb_playlist】的数据库操作Service实现
* @createDate 2025-09-26 14:09:53
 *
*/
@Service
@CacheConfig(cacheNames = "playlistCache")
public class PlaylistServiceImpl extends ServiceImpl<PlaylistMapper, Playlist>
    implements PlaylistService{
    @Autowired
    private PlaylistMapper playlistMapper;
    @Autowired
    private UserFavoriteMapper userFavoriteMapper;
    @Autowired
    private MinioService minioService;
    @Autowired
    private PlaylistBindingService playlistBindingService;
    //分页条件查询
    @Override
    @Cacheable(key = "#playlistDTO.pageNum + '-' + #playlistDTO.pageSize + '-' + #playlistDTO.title + '-' + #playlistDTO.style")
    public DataVo<PageResult<PlayListVo>> getAllPlayLists(PlaylistDTO playlistDTO) {
        //分页查询
        Page<Playlist> page = new Page<>(playlistDTO.getPageNum(), playlistDTO.getPageSize());
        QueryWrapper<Playlist> queryWrapper = new QueryWrapper<>();
        //条件查询
        if (playlistDTO.getTitle() != null && !playlistDTO.getTitle().trim().isEmpty()) {
            queryWrapper.like("title", playlistDTO.getTitle());
        }
        if (playlistDTO.getStyle() != null && !playlistDTO.getStyle().trim().isEmpty()) {
            queryWrapper.eq("style", playlistDTO.getStyle());
        }
        IPage<Playlist> playlistIPage = playlistMapper.selectPage(page, queryWrapper);
        if (playlistIPage.getRecords().size() ==0) {
            return DataVo.success(MessageConstant.DATA_NOT_FOUND,new PageResult<>(0L,null));
        }
        //转换为 PlayListVo
        List<PlayListVo> platListVos = playlistIPage.getRecords().stream()
                .map(playlist -> {
                    PlayListVo platListVo = new PlayListVo();
                    BeanUtils.copyProperties(playlist,platListVo);
                    platListVo.setStyle(playlist.getStyle());
                    return platListVo;
                }).toList();
        return DataVo.success(new PageResult<>(playlistIPage.getTotal(),platListVos));
    }

    //获取推荐歌单
    @Override
    public DataVo<List<PlayListVo>> getRecommendedPlaylists(HttpServletRequest request) {
        // 获取请求头中的 token
        String token = request.getHeader("Authorization");
        if (token != null && token.startsWith("Bearer")) {
            token =  token.substring(7); //去掉 "Bearer " 前缀
        }
        Map<String, Object> map = null;
        if (token != null && !token.isEmpty()) {
            map = JwtUtil.parseToken(token);
        }
        Long userId = null;
        if (map != null) {
            String role = (String) map.get(JwtClaimsConstant.ROLE);
            if (role.equals(RoleEnum.USER.getRole())) {
                Object userIdObj = map.get(JwtClaimsConstant.USER_ID);
                userId = TypeConversionUtil.toLong(userIdObj);
            }
        }
        // 用户未登录，返回随机歌单
        if (userId == null) {
            return DataVo.success(playlistMapper.getRandomPlaylists(10));
        }
        // 获取用户收藏的歌单 ID
        List<Long> favoritePlaylistIds = userFavoriteMapper.getFavoritePlaylistIdsByUserId(userId);
        if (favoritePlaylistIds.size()==0) {
            return DataVo.success(playlistMapper.getRandomPlaylists(10));
        }
        //查询用户收藏的的歌单风格并统计频率
        List<String> favoriteStyles = playlistMapper.getFavoritePlaylistStyles(favoritePlaylistIds);
        List<Long> favoriteStyleIds = userFavoriteMapper.getFavoriteIdsByStyle(favoriteStyles);
        //统计风格id出现的次数
        Map<Long,Long> styleFrequency = favoriteStyleIds.stream()
                .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
        //按风格出现次数降序排序
        List<Long> sortedStyleIds = styleFrequency.entrySet().stream()
                .sorted((a, b) -> Long.compare(b.getValue(), a.getValue()))
                .map(Map.Entry::getKey)
                .collect(Collectors.toList());
        //根据排序后的风格推荐歌单(排除已收藏歌单)
        List<PlayListVo> recommendedPlaylists = playlistMapper.getRecommendedPlaylistsByStyles(sortedStyleIds, favoritePlaylistIds, 10);

        //如果推荐的歌单不足 10 个
        if(recommendedPlaylists.size()<10){
            List<PlayListVo> randomPlaylists = playlistMapper.getRandomPlaylists(10);
            Set<Long> addedPlaylistIds = recommendedPlaylists.stream().map(PlayListVo::getId).collect(Collectors.toSet());

            for(PlayListVo playListVo:randomPlaylists){
                if (recommendedPlaylists.size() >= 10) break;
                if (! addedPlaylistIds.contains(playListVo.getId())) {
                    recommendedPlaylists.add(playListVo);
                }
            }
        }
        return DataVo.success(recommendedPlaylists);
    }

    //获取歌单详细
    @Override
    public DataVo<PlaylistDetailVO> getPlaylistDetail(Long playlistId, HttpServletRequest request) {
        PlaylistDetailVO playlistDetailVO = playlistMapper.getPlaylistDetailById(playlistId);
        // 设置默认状态
        // 设置默认状态
        List<SongVo> songVOList = playlistDetailVO.getSongs();
        songVOList.forEach(songVO -> songVO.setLikeStatus(LikeStatusEnum.DEFAULT.getId()));
        playlistDetailVO.setLikeStatus(LikeStatusEnum.DEFAULT.getId());

        // 获取请求头中的 token
        String token = request.getHeader("Authorization");
        if (token != null && token.startsWith("Bearer ")) {
            token = token.substring(7);  // 去掉 "Bearer " 前缀
        }

        Map<String, Object> map = null;
        if (token != null && !token.isEmpty()) {
            map = JwtUtil.parseToken(token);
        }
        if (map != null) {
            String role = (String) map.get(JwtClaimsConstant.ROLE);
            if (role.equals(RoleEnum.USER.getRole())) {
                Object userIdObj = map.get(JwtClaimsConstant.USER_ID);
                Long userId = TypeConversionUtil.toLong(userIdObj);

                QueryWrapper<UserFavorite> userFavoriteQueryWrapper = new QueryWrapper<>();
                userFavoriteQueryWrapper.eq("user_id", userId);
                userFavoriteQueryWrapper.eq("type", 1);
                userFavoriteQueryWrapper.eq("playList_id", playlistId);
                //获取用户收藏的歌单
                UserFavorite favoritePlaylist = userFavoriteMapper.selectOne(userFavoriteQueryWrapper);
                if (favoritePlaylist != null) {
                    playlistDetailVO.setLikeStatus(LikeStatusEnum.LIKE.getId());
                }

                QueryWrapper<UserFavorite> userFavoriteSongs= new QueryWrapper<>();
                userFavoriteSongs.eq("user_id", userId);
                userFavoriteSongs.eq("type", 0);
                //获取用户收藏的歌曲
                List<UserFavorite> favoriteSongs = userFavoriteMapper.selectList(userFavoriteSongs);
                //获取用户收藏的歌曲 id
                Set<Long> favoriteSongIds = favoriteSongs.stream()
                        .map(UserFavorite::getSongId).collect(Collectors.toSet());
                //检查并更新状态
                for(SongVo songVo:songVOList){
                    if (favoriteSongIds.contains(songVo.getSongId())) {
                        songVo.setLikeStatus(LikeStatusEnum.LIKE.getId());
                    }
                }
            }
        }
        return DataVo.success(playlistDetailVO);
    }
    //添加歌单

    @Override
    @CacheEvict(cacheNames = "playlistCache", allEntries = true)
    public DataVo addPlaylist(PlaylistAddDTO playlistAddDTO) {
        QueryWrapper<Playlist> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("title", playlistAddDTO.getTitle());
        if (playlistMapper.selectCount(queryWrapper) > 0) {
            return DataVo.error(MessageConstant.PLAYLIST + MessageConstant.ALREADY_EXISTS);
        }
        Playlist playlist = new Playlist();
        BeanUtils.copyProperties(playlistAddDTO, playlist);
        playlistMapper.insert(playlist);

       ;
        List<Long> songIds = playlistAddDTO.getSongIds();
        if (songIds.size() > 0) {
            Long playlistId = playlist.getId();
            PlayListBindingDTO bindingDTO = new PlayListBindingDTO();
            bindingDTO.setPlaylistId(playlistId);
            bindingDTO.setSongIds(songIds);
            DataVo songAddResult = playlistBindingService.addSongsToPlaylist(bindingDTO);
            if (songAddResult.getCode() == 1) {
                return DataVo.error("添加失败不存在此id的歌曲");
            }
        }
        return DataVo.success(MessageConstant.ADD + MessageConstant.SUCCESS);
    }

    //更新歌单
    @Override
    @CacheEvict(cacheNames = "playlistCache", allEntries = true)
    public DataVo updatePlaylist(PlaylistUpdateDTO playlistUpdateDTO) {
        Long playlistId = playlistUpdateDTO.getId();

        Playlist playlistByTitle = playlistMapper.selectOne(new QueryWrapper<Playlist>().eq("title", playlistUpdateDTO.getTitle()));
        if (playlistByTitle != null && !playlistByTitle.getId().equals(playlistId)) {
            return DataVo.error(MessageConstant.PLAYLIST + MessageConstant.ALREADY_EXISTS);
        }

        Playlist playlist = new Playlist();
        BeanUtils.copyProperties(playlistUpdateDTO, playlist);
        playlist.setIntroduction(playlistUpdateDTO.getIntro());
        if (playlistMapper.updateById(playlist) == 0) {
            return DataVo.error(MessageConstant.UPDATE + MessageConstant.FAILED);
        }

        return DataVo.success(MessageConstant.UPDATE + MessageConstant.SUCCESS);
    }

    // 更新歌单封面
    @Override
    @CacheEvict(cacheNames = "playlistCache", allEntries = true)
    public DataVo updatePlaylistCover(Long playlistId, String coverUrl) {
        Playlist playlist = playlistMapper.selectById(playlistId);
        String cover = playlist.getCoverUrl();
        if (cover != null && !cover.isEmpty()) {
            minioService.deleteFile(cover);
        }

        playlist.setCoverUrl(coverUrl);
        if (playlistMapper.updateById(playlist) == 0) {
            return DataVo.error(MessageConstant.UPDATE + MessageConstant.FAILED);
        }

        return DataVo.success(MessageConstant.UPDATE + MessageConstant.SUCCESS);
    }

    // 删除歌单

    @Override
    @CacheEvict(cacheNames = "playlistCache", allEntries = true)
    public DataVo deletePlaylist(Long playlistId) {
        // 1. 查询歌单信息，获取封面 URL
        Playlist playlist = playlistMapper.selectById(playlistId);
        if (playlist == null) {
            return DataVo.error(MessageConstant.PLAYLIST + MessageConstant.NOT_FOUND);
        }
        String coverUrl = playlist.getCoverUrl();

        // 2. 先删除 MinIO 里的封面文件
        if (coverUrl != null && !coverUrl.isEmpty()) {
            minioService.deleteFile(coverUrl);
        }

        // 3. 删除数据库中的歌单信息
        if (playlistMapper.deleteById(playlistId) == 0) {
            return DataVo.error(MessageConstant.DELETE + MessageConstant.FAILED);
        }

        return DataVo.success(MessageConstant.DELETE + MessageConstant.SUCCESS);
    }

    // 批量删除歌单

    @Override
    @CacheEvict(cacheNames = "playlistCache", allEntries = true)
    public DataVo deletePlaylists(List<Long> playlistIds) {
        List<Playlist> playlists = playlistMapper.selectBatchIds(playlistIds);
        List<String> coverUrlList = playlists.stream()
                .map(Playlist::getCoverUrl)
                .filter(coverUrl -> coverUrl != null && !coverUrl.isEmpty())
                .toList();

        // 2. 先删除 MinIO 里的封面文件
        for (String coverUrl : coverUrlList) {
            minioService.deleteFile(coverUrl);
        }

        // 3. 删除数据库中的歌单信息
        if (playlistMapper.deleteBatchIds(playlistIds) == 0) {
            return DataVo.error(MessageConstant.DELETE + MessageConstant.FAILED);
        }

        return DataVo.success(MessageConstant.DELETE + MessageConstant.SUCCESS);
    }




    //获取所有歌单信息 不包括歌曲
    @Override
    @Cacheable(key = "#playlistDTO.pageNum + '-' + #playlistDTO.pageSize + '-' + #playlistDTO.title + '-' + #playlistDTO.style + '-admin'")
    public DataVo<PageResult<Playlist>> getAllPlaylistsInfo(PlaylistDTO playlistDTO) {
        // 分页查询
        Page<Playlist> page = new Page<>(playlistDTO.getPageNum(), playlistDTO.getPageSize());
        QueryWrapper<Playlist> queryWrapper = new QueryWrapper<>();
        // 根据 playlistDTO 的条件构建查询条件
        if (playlistDTO.getTitle() != null && !playlistDTO.getTitle().trim().isEmpty()) {
            queryWrapper.like("title", playlistDTO.getTitle());
        }
        if (playlistDTO.getStyle() != null && !playlistDTO.getStyle().trim().isEmpty()) {
            queryWrapper.eq("style", playlistDTO.getStyle());
        }
        // 倒序排序
        queryWrapper.orderByDesc("id");

        IPage<Playlist> playlistPage = playlistMapper.selectPage(page, queryWrapper);
        if (playlistPage.getRecords().size() == 0) {
            return DataVo.success(MessageConstant.DATA_NOT_FOUND, new PageResult<>(0L, null));
        }

        return DataVo.success(new PageResult<>(playlistPage.getTotal(), playlistPage.getRecords()));
    }

}




